package com.gmrz.uas.plugin.sm2;

import com.gmrz.uas.plugin.cert.Convert;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.bouncycastle.asn1.*;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cms.CMSSignedData;
import org.bouncycastle.cms.CMSTypedData;
import org.bouncycastle.cms.SignerInformation;
import org.bouncycastle.cms.SignerInformationStore;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.jcajce.provider.asymmetric.x509.*;
import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.pkcs.PKCS10CertificationRequest;
import org.bouncycastle.util.Store;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import java.security.*;
import java.security.Certificate;
import java.security.KeyFactory;
import java.security.cert.*;
import java.security.cert.CertificateFactory;
import java.security.spec.RSAPublicKeySpec;
import java.util.Arrays;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Iterator;

public class SM2Utils {

    private static final Logger LOG = LogManager.getLogger(SM2Utils.class);
    public static final byte[] DEFAULT_USERID = new byte[]{0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38};

    public static boolean verifySign(byte[] publicKey, byte[] sourceData, byte[] signData) {
        byte[] userid = new byte[]{0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38};
        String publicKeyStr = Convert.toBase64(publicKey);
        String sourceDatayStr = Convert.toBase64(sourceData);
        String signDataStr = Convert.toBase64(signData);
        LOG.debug("verifySign publicKeyStr:" + publicKeyStr);
        LOG.debug("verifySign sourceDatayStr:" + sourceDatayStr);
        LOG.debug("verifySign signDataStr:" + signDataStr);
        if (publicKey == null || publicKey.length == 0) {
            return false;
        }
        if (sourceData == null || sourceData.length == 0) {
            return false;
        }
        byte[] formatedPubKey;
        if (publicKey.length == 64) {
            formatedPubKey = new byte[65];
            formatedPubKey[0] = 0x04;
            System.arraycopy(publicKey, 0, formatedPubKey, 1, publicKey.length);
        } else {
            formatedPubKey = publicKey;
        }
        SM2 sm2 = SM2.Instance();
        ECPoint userKey = sm2.ecc_curve.decodePoint(formatedPubKey);

        SM3Digest sm3 = new SM3Digest();
        byte[] z = sm2.sm2GetZ(userid, userKey);


        sm3.update(z, 0, z.length);
        sm3.update(sourceData, 0, sourceData.length);
        byte[] md = new byte[32];
        sm3.doFinal(md, 0);

        ByteArrayInputStream bis = new ByteArrayInputStream(signData);
        ASN1InputStream dis = new ASN1InputStream(bis);
        SM2Result sm2Result = null;
        try {
//			DERObject derObj = dis.readObject();
//			Enumeration<DERInteger> e = ((ASN1Sequence) derObj).getObjects();
//			BigInteger r = ((DERInteger)e.nextElement()).getValue();
//			BigInteger s = ((DERInteger)e.nextElement()).getValue();
            ASN1Encodable asn1Encodable = dis.readObject();
            ASN1Primitive asn1Primitive = asn1Encodable.toASN1Primitive();
            ASN1Sequence asn1 = (ASN1Sequence) asn1Primitive;
            Enumeration<ASN1Integer> e = asn1.getObjects();
            BigInteger r = e.nextElement().getValue();
            BigInteger s = e.nextElement().getValue();
            sm2Result = new SM2Result();
            sm2Result.r = r;
            sm2Result.s = s;
            sm2.sm2Verify(md, userKey, sm2Result.r, sm2Result.s, sm2Result);
            return sm2Result.r.equals(sm2Result.R);
        } catch (IOException e1) {
            e1.printStackTrace();
            return false;
        }
    }

    public static boolean verifySignRaw(byte[] publicKey, byte[] sourceData, byte[] signData) {
        byte[] userid = new byte[]{0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38};
//        String publicKeyStr = Convert.toBase64(publicKey);
//        String sourceDatayStr = Convert.toBase64(sourceData);
//        String signDataStr = Convert.toBase64(signData);
//        LOG.debug("verifySignRaw publicKeyStr:" + publicKeyStr);
//        LOG.debug("verifySignRaw sourceDatayStr:" + sourceDatayStr);
//        LOG.debug("verifySignRaw signDataStr:" + signDataStr);
        if (publicKey == null || publicKey.length == 0) {
            return false;
        }
        if (sourceData == null || sourceData.length == 0) {
            return false;
        }
        byte[] formatedPubKey;
        if (publicKey.length == 64) {
            formatedPubKey = new byte[65];
            formatedPubKey[0] = 0x04;
            System.arraycopy(publicKey, 0, formatedPubKey, 1, publicKey.length);
        } else {
            formatedPubKey = publicKey;
        }
        SM2 sm2 = SM2.Instance();
        ECPoint userKey = sm2.ecc_curve.decodePoint(formatedPubKey);

        SM3Digest sm3 = new SM3Digest();
        byte[] z = sm2.sm2GetZ(userid, userKey);


        sm3.update(z, 0, z.length);
        sm3.update(sourceData, 0, sourceData.length);
        byte[] md = new byte[32];
        sm3.doFinal(md, 0);

        SM2Result sm2Result = null;
        if (signData != null && signData.length == 64) {
            sm2Result = new SM2Result();
            byte[] r = new byte[32];
            System.arraycopy(signData, 0, r, 0, 32);
            sm2Result.r = new BigInteger(1, r);
            byte[] s = new byte[32];
            System.arraycopy(signData, 32, s, 0, 32);
            sm2Result.s = new BigInteger(1, s);
            sm2.sm2Verify(md, userKey, sm2Result.r, sm2Result.s, sm2Result);
            return sm2Result.r.equals(sm2Result.R);
        }
        return false;
    }

    public static boolean verifySecondLevelCertSign(byte[] publicKey, byte[] rootPublicKey, byte[] sourceData, byte[] signData) {
        String userId = "1234567812345678";
        if (publicKey == null || publicKey.length == 0) {
            return false;
        }
        if (sourceData == null || sourceData.length == 0) {
            return false;
        }
        byte[] formatedPubKey;
        if (publicKey.length == 64) {
            formatedPubKey = new byte[65];
            formatedPubKey[0] = 0x04;
            System.arraycopy(publicKey, 0, formatedPubKey, 1, publicKey.length);
        } else {
            formatedPubKey = publicKey;
        }
        SM2 sm2 = SM2.Instance();
        ECPoint userKey = sm2.ecc_curve.decodePoint(formatedPubKey);
        SM3Digest sm3 = new SM3Digest();
        byte[] z = sm2.sm2GetZ(userId.getBytes(), userKey);
        sm3.update(z, 0, z.length);
        sm3.update(sourceData, 0, sourceData.length);
        byte[] md = new byte[32];
        sm3.doFinal(md, 0);

        byte[] formatedRootPublicKey;
        if (rootPublicKey.length == 64) {
            //添加一字节标识，用于ECPoint解析
            formatedRootPublicKey = new byte[65];
            formatedRootPublicKey[0] = 0x04;
            System.arraycopy(rootPublicKey, 0, formatedRootPublicKey, 1, rootPublicKey.length);
        } else {
            formatedRootPublicKey = rootPublicKey;
        }
        SM2 sm2B = SM2.Instance();
        ECPoint rootPublicKeyP = sm2B.ecc_curve.decodePoint(formatedRootPublicKey);

        ByteArrayInputStream bis = new ByteArrayInputStream(signData);
        ASN1InputStream dis = new ASN1InputStream(bis);
        SM2Result sm2Result = null;
        try {
            ASN1Encodable asn1Encodable = dis.readObject();
            ASN1Primitive asn1Primitive = asn1Encodable.toASN1Primitive();
            ASN1Sequence asn1 = (ASN1Sequence) asn1Primitive;
            Enumeration<ASN1Integer> e = asn1.getObjects();
            BigInteger r = e.nextElement().getValue();
            BigInteger s = e.nextElement().getValue();
            sm2Result = new SM2Result();
            sm2Result.r = r;
            sm2Result.s = s;
            sm2.sm2Verify(md, rootPublicKeyP, sm2Result.r, sm2Result.s, sm2Result);
            return sm2Result.r.equals(sm2Result.R);
        } catch (IOException e1) {
            e1.printStackTrace();
            return false;
        }
    }

    public static Sm2KeyPair generateKeyPair() {
        SM2 sm2 = SM2.Instance();
        AsymmetricCipherKeyPair keypair = sm2.ecc_key_pair_generator.generateKeyPair();
        ECPrivateKeyParameters ecpriv = (ECPrivateKeyParameters) keypair.getPrivate();
        ECPublicKeyParameters ecpub = (ECPublicKeyParameters) keypair.getPublic();


        byte[] priKey = new byte[32];
        byte[] pubKey = new byte[64];

        byte[] bigNumArray = ecpriv.getD().toByteArray();
        System.arraycopy(bigNumArray, bigNumArray[0] == 0 ? 1 : 0, priKey, 0, 32);
        System.arraycopy(ecpub.getQ().getEncoded(false), 1, pubKey, 0, 64);


        return new Sm2KeyPair(priKey, pubKey);
    }

    public static void main(String[] args) {
//		byte[] publicKey = Convert.fromBase64("1mQ3OEyzflkQ4PJhlSQ2UgSxuv17ZAjs0HfyuyZmq9BA_4eB1t0m39BcBzjPGBjglA3_YnibFd460yvmWQ8ejg");
//	 byte[] sourceData = Convert.fromBase64("MIIBWqADAgECAgEBMBQGCCqBHM9VAYN1BggqgRzPVQGDdTBBMQswCQYDVQQGEwJDTjEPMA0GA1UEChMGTEVOT1ZPMQ8wDQYDVQQDEwZST09UQ0ExEDAOBgNVBAcTB0JFSUpJTkcwHhcNMTcwNjA4MTMwNjA5WhcNMjIwNjA3MTMwNjA5WjBBMQswCQYDVQQGEwJDTjEPMA0GA1UEChMGTEVOT1ZPMQ8wDQYDVQQDEwZST09UQ0ExEDAOBgNVBAcTB0JFSUpJTkcwWTATBgcqhkjOPQIBBggqgRzPVQGCLQNCAATWZDc4TLN-WRDg8mGVJDZSBLG6_XtkCOzQd_K7Jmar0ED_h4HW3Sbf0FwHOM8YGOCUDf9ieJsV3jrTK-ZZDx6OozkwNzAJBgNVHRMEAjAAMAsGA1UdDwQEAwID6DAdBgNVHQ4EFgQU2jmj7l5rSw0yVb_vlWAYkK_YBwk");
//	 byte[] signData = Convert.fromBase64("MEQCIHSfpzKt4MGtVXJkvWHW_OVM7fgB5IdmlRmbInAOzKTdAiBfYoATXiNc4Xf3C05rM-5-InaBNRG0RBrfbD5V1KfjPw");

//	 boolean f  = verifySign(publicKey,sourceData,signData);
//	 byte[] publicKey = Convert.fromBase64("PeULAt925tWHajTHvfdXSPP2r8ZjMJeN_FNZTchfEX2ip6oyh59zcjaRUgInPGXRSUQMW6IZHH8XflyPGvTorQ");
//	 byte[] sourceData = Convert.fromBase64("AlXRAAZVIAC_-yaDl_7fpWj3y9I0eSTwonBc-e46KAgHHhpsyHtXeANSIADp7KC6J2hEz4OPtrsAOoGBG8595Te13N0-j5mc-EXdVxVSIACocXVytpw0G248tdaa-4aIqXAuCNj1SrPDTmzkqKbFyBZSAAAFVQQAAQABAAtSCQAwMDRBI0ZGRjMXUkAAPeULAt925tWHajTHvfdXSPP2r8ZjMJeN_FNZTchfEX2ip6oyh59zcjaRUgInPGXRSUQMW6IZHH8XflyPGvTorQ1SBAA4MTI3");
//	 byte[] signData = Convert.fromBase64("JZdGmEW5uVbd9po1N7euA-bWZlquRK4IYxsZp5wZROAxv6k-pco1GIjUpxVjttSy7iMzTvvZHHvZ1WOas0JnSA");
//
//
//	 boolean f  = verifySignRaw(publicKey,sourceData,signData);

        String s = "MIICowYJKoZIhvcNAQcCoIIClDCCApACAQExDjAMBggqgRzPVQGDEQUAMCEGCSqGSIb3DQEHAaAUBBK16y362tqexpy2Kif5yie16e2gggGvMIIBqzCCAUegAwIBAgIBCDAUBggqgRzPVQGDdQYIKoEcz1UBg3UwMjENMAsGA1UEChMEZ21yejEPMA0GA1UEAxMGUk9PVENBMRAwDgYDVQQHEwdCRUlKSU5HMB4XDTE4MDQyNjA1NDI1NFoXDTIxMDQyNTA1NDI1NFowPTELMAkGA1UEBhMCQ04xDTALBgNVBAoTBEdNUloxDTALBgNVBAMTBGFzZGYxEDAOBgNVBAcTB0JFSUpJTkcwWTATBgcqhkjOPQIBBggqgRzPVQGCLQNCAASU7ivrzU7ksBRmCsmytgsas6vxqt88JVzojpt4KE1B-BLMsmipNFq9sexGSVApsRe4vT_oMdwQ_NQkliKEn1-tozkwNzAJBgNVHRMEAjAAMAsGA1UdDwQEAwID6DAdBgNVHQ4EFgQUqrrvVz1j0W7LNFqApC1YLZ4FJP0wFAYIKoEcz1UBg3UGCCqBHM9VAYN1A0gAMEUCIQC_PD_XvBkxG0VDDVOgXPpD_Ij8QRZ9xlRuwypq53qJJQIgfhGGMrU2mYt5DlKpYF0JbrZ7mZ72h7O8U3s93RQtYYIxgaQwgaECAQIwNzAyMQ0wCwYDVQQKEwRnbXJ6MQ8wDQYDVQQDEwZST09UQ0ExEDAOBgNVBAcTB0JFSUpJTkcCAQgwDAYIKoEcz1UBgxEFADAMBggqgRzPVQGDdQUABEcwRQIgGcNNlsBNR8QjxLz2bpps3-cUQ6BBwo1fBMaJMfUF_74CIQCKa_c0esLoNaKZ82LuUD2QvrhqFFQdKeRt7IPNbjUZAg";
        boolean f = verifySM2P7(Convert.fromBase64(s));

    }

    public static boolean verifySM2P7(byte[] p7Data) {
        String userId = "1234567812345678";
        boolean verifyRes = false;
        String s = Convert.toBase64(p7Data);
        //System.out.println("s:"+s);
        try {
            CMSSignedData sig = new CMSSignedData(p7Data);
            Store certs = sig.getCertificates();
            SignerInformationStore signers = sig.getSignerInfos();
            Collection<?> c = signers.getSigners();
            Iterator<?> it = c.iterator();
            SignerInformation signer;
            Collection<?> certCollection;
            Iterator<?> certIt;
            CMSTypedData contentInfo = sig.getSignedContent();
            if (c.size() != 1) {
                throw new Exception();
            }
            while (it.hasNext()) {
//                signer = (SignerInformation)it.next();
//                certCollection = certs.getMatches(signer.getSID());
//                certIt = certCollection.iterator();
//                X509CertificateHolder certHolder = (X509CertificateHolder)certIt.next();
////                X509Certificate cert = new JcaX509CertificateConverter().getCertificate(certHolder);
//
//                byte[] publicKey=new byte[64];
////                PublicKey publicKey1 = cert.getPublicKey();
////                System.arraycopy(publicKey1.getEncoded(), publicKey1.getEncoded().length-64, publicKey, 0, 64);
//                System.arraycopy(certHolder.getSubjectPublicKeyInfo().getPublicKeyData().getEncoded(), certHolder.getSubjectPublicKeyInfo().getPublicKeyData().getEncoded().length-64, publicKey, 0, 64);
//
//                byte[] signature = signer.getSignature();
//
//                byte[] data = (byte[])contentInfo.getContent();
//
//                verifyRes = SM2Utils.verifySign(SM2Utils.DEFAULT_USERID,publicKey,data,signature);
//                //ONLY ONE CERTIFICATE , CAN RETURN NOW
//                return verifyRes;


                signer = (SignerInformation) it.next();
                certCollection = certs.getMatches(signer.getSID());
                certIt = certCollection.iterator();
                X509CertificateHolder certHolder = (X509CertificateHolder) certIt.next();

                byte[] publicKey = new byte[64];
                byte[] publicKeyByte = certHolder.getSubjectPublicKeyInfo().getPublicKeyData().getEncoded();
                System.arraycopy(publicKeyByte, publicKeyByte.length - 64, publicKey, 0, 64);

                //System.out.print("pubkey:" + UtilByte.byte2hex(publicKeyByte) + "\n");

                byte[] signature = signer.getSignature();
                //System.out.print("signature:" + UtilByte.byte2hex(signature) + "\n");

                byte[] data = (byte[]) contentInfo.getContent();
                //System.out.print("data:" + UtilByte.byte2hex(data) + "\n");

                verifyRes = verifySign(publicKey, data, signature);
                return verifyRes;
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
        }
        return false;
    }
    public static  byte[] SHA256_DIGEST_INFO = {
            0x30,0x31,0x30,0x0d,0x06,0x09,0x60,(byte) 0x86,
            0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,
            0x00,0x04,0x20};
    public static boolean verifyRSAP7(byte[] p7Data) {
        String userId = "1234567812345678";
        boolean verifyRes = false;
        String s = Convert.toBase64(p7Data);
        //System.out.println("s:"+s);
        try {
            CMSSignedData sig = new CMSSignedData(p7Data);
            Store certs = sig.getCertificates();
            SignerInformationStore signers = sig.getSignerInfos();
            Collection<?> c = signers.getSigners();
            Iterator<?> it = c.iterator();
            SignerInformation signer;
            Collection<?> certCollection;
            Iterator<?> certIt;
            CMSTypedData contentInfo = sig.getSignedContent();
            if (c.size() != 1) {
                throw new Exception();
            }
            while (it.hasNext()) {
//                signer = (SignerInformation)it.next();
//                certCollection = certs.getMatches(signer.getSID());
//                certIt = certCollection.iterator();
//                X509CertificateHolder certHolder = (X509CertificateHolder)certIt.next();
////                X509Certificate cert = new JcaX509CertificateConverter().getCertificate(certHolder);
//
//                byte[] publicKey=new byte[64];
////                PublicKey publicKey1 = cert.getPublicKey();
////                System.arraycopy(publicKey1.getEncoded(), publicKey1.getEncoded().length-64, publicKey, 0, 64);
//                System.arraycopy(certHolder.getSubjectPublicKeyInfo().getPublicKeyData().getEncoded(), certHolder.getSubjectPublicKeyInfo().getPublicKeyData().getEncoded().length-64, publicKey, 0, 64);
//
//                byte[] signature = signer.getSignature();
//
//                byte[] data = (byte[])contentInfo.getContent();
//
//                verifyRes = SM2Utils.verifySign(SM2Utils.DEFAULT_USERID,publicKey,data,signature);
//                //ONLY ONE CERTIFICATE , CAN RETURN NOW
//                return verifyRes;


                signer = (SignerInformation) it.next();
                certCollection = certs.getMatches(signer.getSID());
                certIt = certCollection.iterator();
                X509CertificateHolder certHolder = (X509CertificateHolder) certIt.next();



                //System.out.println(certHolder.getSubjectPublicKeyInfo().parsePublicKey().toString());


                ASN1Sequence seq = (ASN1Sequence)(certHolder.getSubjectPublicKeyInfo().getPublicKey().toASN1Primitive());
                ASN1Encodable[] ss = seq.toArray();
                ASN1Integer  a1 = (ASN1Integer) ss[0];
                ASN1Integer  a2 = (ASN1Integer) ss[1];

                byte[] bts = certHolder.getSubjectPublicKeyInfo().getPublicKey().getEncoded();
                KeyStore keyStore = KeyStore.getInstance("JKS");

                KeyFactory keyFactory = KeyFactory.getInstance("RSA");

                PublicKey publicKey = keyFactory.generatePublic(new RSAPublicKeySpec(a1.getValue(), a2.getValue()));


                //System.out.println(Base64.getEncoder().encodeToString(signer.getSignature()));




//                byte[] publicKey = new byte[64];
//                byte[] publicKeyByte = certHolder.getSubjectPublicKeyInfo().getPublicKeyData().getEncoded();
//                System.arraycopy(publicKeyByte, publicKeyByte.length - 64, publicKey, 0, 64);

                //System.out.print("pubkey:" + UtilByte.byte2hex(publicKeyByte) + "\n");

                byte[] signature = signer.getSignature();
                //System.out.print("signature:" + UtilByte.byte2hex(signature) + "\n");

                byte[] data = (byte[]) contentInfo.getContent();
                //System.out.print("data:" + UtilByte.byte2hex(data) + "\n");

                //verifyRes = verifySign(publicKey, data, signature);
                //byte[] signedKRDBytesP1 = new byte[52];
                MessageDigest messageDigest;
                messageDigest = MessageDigest.getInstance("SHA-256");
                messageDigest.update(data);
                byte[] signedData =  messageDigest.digest();
                byte[] oDATA = new byte[51];
                //oDATA[oDATA.length-1] = 0x00;

                System.arraycopy(SHA256_DIGEST_INFO, (short)0, oDATA, (short)(0), (short)SHA256_DIGEST_INFO.length);
                System.arraycopy(signedData, (short)0, oDATA, (short)(SHA256_DIGEST_INFO.length), (short)signedData.length);



                Signature sig111 = Signature.getInstance("RSA","BC");
                sig111.initVerify(publicKey);
                sig111.update(oDATA);
                return sig111.verify(signature);

            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
        }
        return false;
    }

    public static org.bouncycastle.asn1.x509.Certificate getCert(byte[] certBytes) throws Exception{
        InputStream inStream = new ByteArrayInputStream(certBytes);
        ASN1Sequence seq = null;
        ASN1InputStream aIn;
        byte[] pk = null;
        aIn = new ASN1InputStream(inStream);
        seq = (ASN1Sequence)aIn.readObject();
        org.bouncycastle.asn1.x509.Certificate cert = org.bouncycastle.asn1.x509.Certificate.getInstance(seq);
//        org.bouncycastle.jcajce.provider.asymmetric.x509.CertificateFactory cf = new org.bouncycastle.jcajce.provider.asymmetric.x509.CertificateFactory();
//        InputStream is1 = new ByteArrayInputStream(cert.getEncoded());
//        java.security.cert.Certificate theCert = (java.security.cert.Certificate) cf.engineGenerateCertificate(is1);
//        is1.close();
//        PublicKey publicKey = theCert.getPublicKey();
        return cert;
    }

    public static byte[] getDN(byte[] p10Data) throws NoSuchAlgorithmException, SignatureException, IOException {
        PKCS10CertificationRequest pkcs10CertificationRequest = new PKCS10CertificationRequest(p10Data);
        X500Name x500Name = pkcs10CertificationRequest.getSubject();
        return x500Name.toString().getBytes();
    }

    public static byte[] sign(byte[] userId, byte[] privateKey, byte[] sourceData) throws Exception {
        if (privateKey == null || privateKey.length == 0) {
            return null;
        }

        if (sourceData == null || sourceData.length == 0)
        {
            return null;
        }

        SM2 sm2 = SM2.Instance();
        BigInteger userD = new BigInteger(1, Arrays.copyOfRange(privateKey, 0, 32));
        ECPoint userKey = sm2.ecc_point_g.multiply(userD).normalize();
        SM3Digest sm3 = new SM3Digest();
        byte[] z = sm2.sm2GetZ(userId, userKey);
        sm3.update(z, 0, z.length);
        sm3.update(sourceData, 0, sourceData.length);
        byte[] md = new byte[32];
        sm3.doFinal(md, 0);
        SM2Result sm2Result = new SM2Result();
        sm2.sm2sign2(md, userD, userKey, sm2Result);
        DERInteger d_r = new DERInteger(sm2Result.r);
        DERInteger d_s = new DERInteger(sm2Result.s);
        ASN1EncodableVector v2 = new ASN1EncodableVector();
        v2.add(d_r);
        v2.add(d_s);
        DERSequence sign = new DERSequence(v2);
        return sign.getEncoded();
    }

    public static byte[] sm2original(byte[] p7Data) {
        String userId = "1234567812345678";
        boolean verifyRes = false;
        String s = Convert.toBase64(p7Data);

        try {
            CMSSignedData sig = new CMSSignedData(p7Data);
            Store certs = sig.getCertificates();
            SignerInformationStore signers = sig.getSignerInfos();
            Collection<?> c = signers.getSigners();
            Iterator<?> it = c.iterator();
            SignerInformation signer;
            Collection<?> certCollection;
            Iterator<?> certIt;
            CMSTypedData contentInfo = sig.getSignedContent();
            if (c.size() != 1) {
                throw new Exception();
            }
            while (it.hasNext()) {

                signer = (SignerInformation) it.next();
                certCollection = certs.getMatches(signer.getSID());
                certIt = certCollection.iterator();
                X509CertificateHolder certHolder = (X509CertificateHolder) certIt.next();

                byte[] data = (byte[]) contentInfo.getContent();
                //System.out.print("data:" + UtilByte.byte2hex(data) + "\n");

                return data;
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
        }
        return null;
    }

    public static byte[] rsaoriginal(byte[] p7Data) {
        String userId = "1234567812345678";
        boolean verifyRes = false;
        String s = Convert.toBase64(p7Data);
        //System.out.println("s:"+s);
        try {
            CMSSignedData sig = new CMSSignedData(p7Data);
            Store certs = sig.getCertificates();
            SignerInformationStore signers = sig.getSignerInfos();
            Collection<?> c = signers.getSigners();
            Iterator<?> it = c.iterator();
            SignerInformation signer;
            Collection<?> certCollection;
            Iterator<?> certIt;
            CMSTypedData contentInfo = sig.getSignedContent();
            if (c.size() != 1) {
                throw new Exception();
            }
            while (it.hasNext()) {
//                signer = (SignerInformation) it.next();
//                certCollection = certs.getMatches(signer.getSID());
//                certIt = certCollection.iterator();
//                X509CertificateHolder certHolder = (X509CertificateHolder) certIt.next();
//
//
//
//                ASN1Sequence seq = (ASN1Sequence)(certHolder.getSubjectPublicKeyInfo().getPublicKey().toASN1Primitive());
//                ASN1Encodable[] ss = seq.toArray();
//                ASN1Integer  a1 = (ASN1Integer) ss[0];
//                ASN1Integer  a2 = (ASN1Integer) ss[1];
//
//                byte[] bts = certHolder.getSubjectPublicKeyInfo().getPublicKey().getEncoded();
//                KeyStore keyStore = KeyStore.getInstance("JKS");
//
//                KeyFactory keyFactory = KeyFactory.getInstance("RSA");
//
//                PublicKey publicKey = keyFactory.generatePublic(new RSAPublicKeySpec(a1.getValue(), a2.getValue()));
//
//                byte[] signature = signer.getSignature();
//                //System.out.print("signature:" + UtilByte.byte2hex(signature) + "\n");

                byte[] data = (byte[]) contentInfo.getContent();

//                MessageDigest messageDigest;
//                messageDigest = MessageDigest.getInstance("SHA-256");
//                messageDigest.update(data);
//                byte[] signedData =  messageDigest.digest();
//                byte[] oDATA = new byte[51];
//                //oDATA[oDATA.length-1] = 0x00;
//
//                System.arraycopy(SHA256_DIGEST_INFO, (short)0, oDATA, (short)(0), (short)SHA256_DIGEST_INFO.length);
//                System.arraycopy(signedData, (short)0, oDATA, (short)(SHA256_DIGEST_INFO.length), (short)signedData.length);
//
//
//
//
//                Signature sig111 = Signature.getInstance("RSA","BC");
//                sig111.initVerify(publicKey);
//                sig111.update(oDATA);
                return data;

            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
        }
        return null;
    }


}
